import createjs from "createjs-ts";
import cjs = createjs
import BaseView from "./BaseView";
//@ts-ignore
import Box2D from '@/Box2dWeb-2.1.a.3.js'
import b2Vec2 = Box2D.Common.Math.b2Vec2;
import b2World = Box2D.Dynamics.b2World
import b2BodyDef = Box2D.Dynamics.b2BodyDef
import b2Body = Box2D.Dynamics.b2Body
import b2FixtureDef = Box2D.Dynamics.b2FixtureDef
import b2DebugDraw = Box2D.Dynamics.b2DebugDraw
import b2PolygonShape = Box2D.Collision.Shapes.b2PolygonShape
import b2CircleShape=Box2D.Collision.Shapes.b2CircleShape
import { GameConfig } from "../Const";
//时间步
const timeStep = 1 / 30;
//速率约束解算器计算次数
const velIterations = 10;
//位置约束解算器计算次数
const posIterations = 10;
//多边形
const polygonShape = new b2PolygonShape()
//刚体
const bodyDef = new b2BodyDef();
//夹具
const fixtureDef = new b2FixtureDef();
//单位换算，一米等于30像素
const worldScale = 30

export default class MainView extends BaseView {
  	private world: b2World
	private arrow:cjs.Shape
	private txt:cjs.Text=new cjs.Text('Hello World','20px Arial','back')
	private axis=new cjs.Shape()
	constructor() {
		super();
		this.addChild(this.axis)
		const check=()=>{
			if(this.stage){
				console.log('MainView stage ok')
				this.addChild(this.txt)
				//创建世界
				this.createWorld()
				//创建边界
				this.createGroundBox()
				//创建重力指针
				this.arrow=this.createGravityArrow()
				//每帧在舞台刷新后，更新世界
				this.stage.on('drawend',()=>{
					//this.updateWorld()
				})
				//隐藏加载页面
				document.getElementById('splash').style.display='none'
				//
				this.stage.canvas.ontouchstart=()=>{
					//
					this.createBall()
				}
				if (window.DeviceOrientationEvent) {
					// 获取设备方向信息
					window.addEventListener('deviceorientation',(event)=>{
						const alpha = event.alpha||0; // 绕 Z 轴旋转的角度
						const beta = event.beta||0;   // 绕 X 轴旋转的角度（前后翻转）
						const gamma = event.gamma||0; // 绕 Y 轴旋转的角度（左右翻转）
						this.refreshGravityArrow(alpha, beta, gamma)
						//
						
						this.txt.text='alpha（z）: ' + alpha.toFixed(2) + '\nbeta（x）: ' + beta.toFixed(2) + '\ngamma（y）: ' + gamma.toFixed(2);
					})
				}else{
					alert('Device Orientation is not supported.')
				}
			}else{
				setTimeout(check,500)
			}
		}
		setTimeout(check,500)
	}
	private createGravityArrow():cjs.Shape{
		const WIDTH = GameConfig.visibleWidth;
		const arrow = new cjs.Shape()
		arrow.graphics.beginFill('back').drawRect(0, 0, 2, 100).endFill();
		arrow.setTransform(WIDTH / 2, 10)
		this.addChild(arrow)
		return arrow
	}
  	private createWorld():void{
    	//重力加速度，一个物体在地球表面自由下落的加速度近似为9.81m/s^2（米每平方秒）
		const gravity = new b2Vec2(0, 9.81)
		//允许刚体睡眠
		const sleep = true
		//创建世界
		this.world = new b2World(gravity, sleep)
		//创建调试绘图
		this.debugDraw()
  	}
  	private debugDraw():void{
    	const debugDraw = new b2DebugDraw()
		const canvas=this.stage.canvas
		const debugSprite = canvas.getContext("2d")
		//container.addChild(debugSprite)
		debugDraw.SetSprite(debugSprite)
		debugDraw.SetDrawScale(worldScale)
		debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit)
		debugDraw.SetFillAlpha(0.5)
		this.world.SetDebugDraw(debugDraw)
  	}
	private createGroundBox():void{
		const WIDTH = GameConfig.stageWidth;
		const HEIGHT = GameConfig.stageHeight;
		console.log('createGroundBox',WIDTH,HEIGHT)
		//地面
		polygonShape.SetAsBox(this.unitConversion(WIDTH / 2), this.unitConversion(10));
		this.createBody(WIDTH / 2, HEIGHT, polygonShape, 3, 0.2, 0.2, 0);
		//左边
		polygonShape.SetAsBox(this.unitConversion(10), this.unitConversion(HEIGHT / 2));
		this.createBody(0, HEIGHT / 2, polygonShape, 3, 0.2, 0.2, 0);
		//右边
		polygonShape.SetAsBox(this.unitConversion(10), this.unitConversion(HEIGHT / 2));
		this.createBody(WIDTH, HEIGHT / 2, polygonShape, 3, 0.2, 0.2, 0);
		//顶部
		polygonShape.SetAsBox(this.unitConversion(WIDTH / 2), this.unitConversion(10));
		this.createBody(WIDTH / 2, 0, polygonShape, 3, 0.2, 0.2, 0);
	}
	private createBody(pX:number, pY:number, shape:b2PolygonShape, density:number, restitution:number, friction:number, type:number, s?:string, asset?:cjs.DisplayObject) {
		bodyDef.position.Set(pX / worldScale, pY / worldScale);
		bodyDef.type = type;
		bodyDef.userData = new Object();
		bodyDef.userData.name = s;
		bodyDef.userData.asset = asset;
		fixtureDef.shape = shape;
		fixtureDef.density = density;
		fixtureDef.restitution = restitution;
		fixtureDef.friction = friction;
		var body = this.world.CreateBody(bodyDef);
		body.CreateFixture(fixtureDef);
		if (asset) this.addChild(asset);
		return body;
	}
	private unitConversion(value:number):number{
		return value / worldScale;
	}
	private updateWorld() {
		const gravity = new b2Vec2(0, 9.81)
		this.world.SetGravity(gravity)
		//更新模拟
		this.world.Step(timeStep, velIterations, posIterations);
		//调试绘制
		this.world.DrawDebugData();
		//清除作用力
		this.world.ClearForces();
	}
	private createBall():void{
		const WIDTH = GameConfig.visibleWidth;
		//刚体
		const bodyDef=new b2BodyDef();
		bodyDef.type=2;
		//圆形
		const circleShape=new b2CircleShape();
		//夹具
		const fixtureDef=new b2FixtureDef();
		const body=this.world.CreateBody(bodyDef);

		circleShape.SetRadius(this.unitConversion(20));
		circleShape.SetLocalPosition(new b2Vec2(this.unitConversion(WIDTH/2),this.unitConversion(100)));
		fixtureDef.shape=circleShape;
		body.CreateFixture(fixtureDef);
	}
	//刷新重力箭头
	private refreshGravityArrow(alpha:number,beta:number,gamma:number):void{
		const r=beta/180*Math.PI
		const len=Math.sin(r)*100
		this.arrow.graphics.clear()
		this.arrow.graphics.beginFill('back').drawRect(0, 0, 2, len).endFill()
		this.arrow.rotation=-gamma
		//
		const {visibleWidth,visibleHeight}=GameConfig
		this.axis.graphics.clear()
		this.axis.graphics.beginStroke('red')
		this.axis.graphics.moveTo(visibleWidth/2, visibleHeight/2)
		if(alpha<180){
			this.axis.graphics.lineTo(visibleWidth/2+100*Math.cos(alpha/180*Math.PI), visibleHeight/2+100*Math.sin(alpha/180*Math.PI))
		}else{
			this.axis.graphics.lineTo(visibleWidth/2+100*Math.cos((360-alpha)/180*Math.PI), visibleHeight/2+100*Math.sin((360-alpha)/180*Math.PI))
		}
		
		this.axis.graphics.beginStroke('green')
		this.axis.graphics.moveTo(visibleWidth/2, visibleHeight/2)
		this.axis.graphics.lineTo(visibleWidth/2, visibleHeight/2-100)
		this.axis.graphics.endStroke()
	}
}